﻿using System;
using System.Collections.Generic;

namespace DataCoreTechnologies.SqlServer
{
   /// <summary>
   /// Contains information about a database schema and the objects it contains.
   /// </summary>
   public sealed class Schema
   {
      #region Public
      //Properties
      /// <summary>
      /// A number that uniquely identifies this class instance.
      /// </summary>
      public Guid InstanceId { get; internal set; }
      /// <summary>
      /// The database this schema belongs to.
      /// </summary>
      public Database Database { get; private set; }
      /// <summary>
      /// The title used to uniquely identify this schema within the database.
      /// </summary>
      public string Name { get; internal set; }
      /// <summary>
      /// The schema that this schema is derived from.
      /// </summary>
      public Schema Owner { get; internal set; }
      /// <summary>
      /// A short explanation explaining the purpose of this schema.
      /// </summary>
      public string Description { get; internal set; }
      /// <summary>
      /// A collection of functions belonging to this schema.
      /// </summary>
      public IEnumerable<Function> Functions
      {
         get
         {
             for (int index = 0; index < _functions.Count; index++)
             {
                 yield return _functions[index];
             }
         }
      }
      /// <summary>
      /// A collection of stored procedures belonging to this schema.
      /// </summary>
      public IEnumerable<StoredProcedure> StoredProcedures
      {
         get
         {
             for (int index = 0; index < _storedProcedures.Count; index++)
             {
                 yield return _storedProcedures[index];
             }
         }
      }
      /// <summary>
      /// A collection of tables belonging to this schema.
      /// </summary>
      public IEnumerable<Table> Tables
      {
         get
         {
             for (int index = 0; index < _tables.Count; index++)
             {
                 yield return _tables[index];
             }
         }
      }
      /// <summary>
      /// A collection of views belonging to this schema.
      /// </summary>
      public IEnumerable<View> Views
      {
         get
         {
             for (int index = 0; index < _views.Count; index++)
             {
                 yield return _views[index];
             }
         }
      }
      /// <summary>
      /// A collection of user types belonging to this schema.
      /// </summary>
      public IEnumerable<UserType> UserTypes
      {
         get
         {
             for (int index = 0; index < _userTypes.Count; index++)
             {
                 yield return _userTypes[index];
             }
         }
      }
      /// <summary>
      /// A collection of extended properties belonging to this schema.
      /// </summary>
      public IEnumerable<ExtendedProperty> ExtendedProperties
      {
         get
         {
             for (int index = 0; index < _extendedProperties.Count; index++)
             {
                 yield return _extendedProperties[index];
             }
         }
      }
      #endregion Public
      #region Internal
      //Constructor
      /// <summary>
      /// Creates an instance of a schema and associates it to the database specified by the parameter.
      /// </summary>
      /// <param name="container">The database that this schema belongs to.</param>
      internal Schema(Database container)
      {
         InstanceId = System.Guid.NewGuid();
         Database = container;
      }
      //Properties
      /// <summary>
      /// A number used to uniquely identify this schema in the database.
      /// </summary>
      internal int Id { get; set; }
      //Methods
      /// <summary>
      /// Associates a function with this schema.
      /// </summary>
      /// <param name="function">A function that belongs to this schema.</param>
      internal void AddFunction(Function function) { _functions.Add(function); }
      /// <summary>
      /// Associates a stored procedure with this schema.
      /// </summary>
      /// <param name="function">A stored procedure that belongs to this schema.</param>
      internal void AddStoredProcedure(StoredProcedure storedProcedure) { _storedProcedures.Add(storedProcedure); }
      /// <summary>
      /// Associates a table with this schema.
      /// </summary>
      /// <param name="function">A table that belongs to this schema.</param>
      internal void AddTable(Table table) { _tables.Add(table); }
      /// <summary>
      /// Associates a view with this schema.
      /// </summary>
      /// <param name="function">A view that belongs to this schema.</param>
      internal void AddView(View view) { _views.Add(view); }
      /// <summary>
      /// Associates a user type with this schema.
      /// </summary>
      /// <param name="function">A user type that belongs to this schema.</param>
      internal void AddUserType(UserType userType) { _userTypes.Add(userType); }
      /// <summary>
      /// Disassociates any user types from this schema.
      /// </summary>
      internal void ClearUserTypes() { _userTypes.Clear(); }
      /// <summary>
      /// Associates a extended property with this schema.
      /// </summary>
      /// <param name="function">A extended property that belongs to this schema.</param>
      internal void AddExtendedProperty(ExtendedProperty extendedProperty) { _extendedProperties.Add(extendedProperty); }
      #endregion Internal
      #region Private
      //Properties
      private List<Function> _functions = new List<Function>();
      private List<StoredProcedure> _storedProcedures = new List<StoredProcedure>();
      private List<Table> _tables = new List<Table>();
      private List<View> _views = new List<View>();
      private List<UserType> _userTypes = new List<UserType>();
      private List<ExtendedProperty> _extendedProperties = new List<ExtendedProperty>();
      #endregion Private
   }
}
